package com.gitee.wsl.doc.prosemirror.transform.internal

//import com.gitee.wsl.doc.prosemirror.model.content.ContentMatch
//import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
//import com.gitee.wsl.doc.prosemirror.model.mark.Mark
//import com.gitee.wsl.doc.prosemirror.model.node.Node
//import com.gitee.wsl.doc.prosemirror.model.Whitespace
//import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
//import com.gitee.wsl.doc.prosemirror.model.mark.MarkType
//import com.gitee.wsl.doc.prosemirror.model.node.NodeType
//import com.gitee.wsl.doc.prosemirror.transform.Transform
//import com.gitee.wsl.doc.prosemirror.transform.step.AddMarkStep
//import com.gitee.wsl.doc.prosemirror.transform.step.RemoveMarkStep
//import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceStep
//import com.gitee.wsl.doc.prosemirror.transform.step.Step
//import kotlin.math.max
//import kotlin.math.min
//
//@Suppress("ComplexMethod")
//internal fun addMark(tr: Transform, from: Int, to: Int, mark: Mark) {
//    val removed = mutableListOf<Step>()
//    val added = mutableListOf<Step>()
//    var removing: RemoveMarkStep? = null
//    var adding: AddMarkStep? = null
//    tr.doc.nodesBetween(from, to) { node: Node, pos: Int, parent: Node?, index: Int ->
//        if (!node.isInline) return@nodesBetween true
//        val marks = node.marks
//        if (!mark.isInSet(marks) && parent!!.type.allowsMarkType(mark.type)) {
//            val start = max(pos, from)
//            val end = min(pos + node.nodeSize, to)
//            val newSet = mark.addToSet(marks)
//
//            for (mark in marks) {
//                if (!mark.isInSet(newSet)) {
//                    val r = removing
//                    if (r != null && r.to == start && r.mark == mark) {
//                        r.to = end
//                    } else {
//                        removing = RemoveMarkStep(start, end, mark).also { removed.add(it) }
//                    }
//                }
//            }
//
//            val currentAdding = adding
//            if (currentAdding != null && currentAdding.to == start) {
//                currentAdding.to = end
//            } else {
//                adding = AddMarkStep(start, end, mark).also { added.add(it) }
//            }
//        }
//        false
//    }
//
//    removed.forEach { s -> tr.step(s) }
//    added.forEach { s -> tr.step(s) }
//}
//
//internal fun removeMark(tr: Transform, from: Int, to: Int, mark: Mark?) {
//    val matched = mutableListOf<MatchedMark>()
//    var step = 0
//    tr.doc.nodesBetween(from, to) { node: Node, pos: Int, parent: Node?, index: Int ->
//        if (!node.isInline) return@nodesBetween true
//        step++
//        var toRemove: List<Mark>? = null
//        if (mark != null) {
//            if (mark.isInSet(node.marks)) toRemove = listOf(mark)
//        } else {
//            toRemove = node.marks
//        }
//        if (toRemove != null && toRemove.isNotEmpty()) {
//            val end = min(pos + node.nodeSize, to)
//            for (style in toRemove) {
//                var found: MatchedMark? = null
//                for (m in matched) {
//                    if (m.step == step - 1 && style == m.style) found = m
//                }
//                if (found != null) {
//                    found.to = end
//                    found.step = step
//                } else {
//                    matched.add(MatchedMark(style, from = max(pos, from), to = end, step))
//                }
//            }
//        }
//        false
//    }
//    matched.forEach { m ->
//        tr.step(RemoveMarkStep(m.from, m.to, m.style))
//    }
//}
//
//data class MatchedMark(val style: Mark, val from: Int, var to: Int, var step: Int)
//
//internal fun removeMark(tr: Transform, from: Int, to: Int, mark: MarkType?) {
//    //data class MatchedMark(val style: Mark, val from: Int, var to: Int, var step: Int)
//    val matched = mutableListOf<MatchedMark>()
//    var step = 0
//    tr.doc.nodesBetween(from, to) { node: Node, pos: Int, parent: Node?, index: Int ->
//        if (!node.isInline) return@nodesBetween false
//        step++
//        var toRemove: MutableList<Mark>? = null
//        if (mark != null) {
//            var set = node.marks
//            var found = mark.isInSet(set)
//            while (found != null) {
//                if (toRemove == null) toRemove = mutableListOf()
//                toRemove.add(found)
//                set = found.removeFromSet(set)
//                found = mark.isInSet(set)
//            }
//        } else {
//            toRemove = node.marks.toMutableList()
//        }
//        if (toRemove != null && toRemove.isNotEmpty()) {
//            val end = min(pos + node.nodeSize, to)
//            for (style in toRemove) {
//                var found: MatchedMark? = null
//                for (m in matched) {
//                    if (m.step == step - 1 && style == m.style) found = m
//                }
//                if (found != null) {
//                    found.to = end
//                    found.step = step
//                } else {
//                    matched.add(MatchedMark(style, from = max(pos, from), to = end, step))
//                }
//            }
//        }
//        false
//    }
//    matched.forEach { m ->
//        tr.step(RemoveMarkStep(m.from, m.to, m.style))
//    }
//}
//
//internal fun clearIncompatible(
//    tr: Transform,
//    pos: Int,
//    parentType: NodeType,
//    match: ContentMatch? = parentType.contentMatch,
//    clearNewlines: Boolean = true
//) {
//    var match = match ?: parentType.contentMatch
//    val node = tr.doc.nodeAt(pos)!!
//    val replSteps = mutableListOf<Step>()
//    var cur = pos + 1
//    for (i in 0 until node.childCount) {
//        val child = node.child(i)
//        val end = cur + child.nodeSize
//        val allowed = match.matchType(child.type)
//        if (allowed == null) {
//            replSteps.add(ReplaceStep(cur, end, Slice.empty))
//        } else {
//            match = allowed
//            for (j in 0 until child.marks.size)
//                if (!parentType.allowsMarkType(child.marks[j].type)) {
//                    tr.step(RemoveMarkStep(cur, end, child.marks[j]))
//                }
//            if (clearNewlines && child.isText && parentType.whitespace != Whitespace.PRE) {
//                val newline = Regex("\r?\n|\r")
//                var slice: Slice? = null
//                val text = child.text ?: ""
//                newline.findAll(text).forEach {
//                    if (slice == null) {
//                        slice = Slice(
//                            Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))),
//                            0,
//                            0
//                        )
//                    }
//                    replSteps.add(ReplaceStep(cur + it.range.first, cur + it.range.last + 1, slice!!))
//                }
//            }
//        }
//        cur = end
//    }
//    if (!match.validEnd) {
//        val fill = match.fillBefore(Fragment.empty, true)
//        tr.replace(cur, cur, Slice(fill!!, 0, 0))
//    }
//    for (i in replSteps.size - 1 downTo 0) {
//        tr.step(replSteps[i])
//    }
//}
